float4x4 xWorldViewProjection;
float4x4 xWorld;
float4 xColor;
float3 xLightPos;
float3 xCameraAngle;
float3 xCameraPos;

Texture xTexture;

sampler TextureSampler = sampler_state { texture = <xTexture> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};
struct VertexToPixel
{
    float4 Position     : POSITION;    
    float2 TexCoords    : TEXCOORD0;
};

struct MyVertexToPixel
{
    float4 Position     : POSITION;    
    float4 Color		: COLOR0;
	float LightingFactor: TEXCOORD0;
};

struct PixelToFrame
{
    float4 Color        : COLOR0;
};

// Technique: SIMPLEST!

VertexToPixel SimplestVertexShader( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0)
{
    VertexToPixel Output = (VertexToPixel)0;
    
    Output.Position =mul(inPos, xWorldViewProjection);
    Output.TexCoords = inTexCoords;

    return Output;
}

PixelToFrame OurFirstPixelShader(VertexToPixel PSIn)
{
    PixelToFrame Output = (PixelToFrame)0;    

    PSIn.TexCoords.y--;
    Output.Color = tex2D(TextureSampler, PSIn.TexCoords);

    return Output;
}

technique Simplest
{
    pass Pass0
    {
        VertexShader = compile vs_2_0 SimplestVertexShader();
        PixelShader = compile ps_2_0 OurFirstPixelShader();
    }
}

// Technique: COLORED!

MyVertexToPixel ColoredVS( float4 inPos : POSITION, float3 inNormal: NORMAL)
{	
	MyVertexToPixel Output = (MyVertexToPixel)0;
    
	Output.Position = mul(inPos, xWorldViewProjection);
	Output.Color = xColor;
	//Normal should remain plain. We need to find the component that is orthogonal to the camera view plane.
	//Except not. Let me lay it on the line for ya.
	//float3 Normal = normalize(mul(inNormal, xWorldViewProjection));
	//float3 pos3D = mul(inPos, xWorldViewProjection);
	//float3 lightDir = normalize(pos3D - xLightPos);
	//Output.LightingFactor = dot(Normal, -lightDir);
	
	//STEP !
	//Normalize light source vector.
	float3 pos3D = mul(inPos, xWorld);
	
	float3 lightSource = normalize(pos3D - xLightPos);

	//STEP @
	//Find the component of the source light parallel to the normal
	//Would normally (get it?) divide by the magnitude of the normal, but since it is normalized, the magnitude is 1.
	float lightGathered = dot(-lightSource, inNormal);

	//STEP #
	//Find the component of the resulting light beam that is orthogonal to the camera plane
	float lightReflected = 1;//dot(inNormal, -normalize(pos3D - xCameraPos));

	//STEP $
	//This results in a lighting vector on the scale of 0-1.
	float totalReflection = lightReflected * lightGathered;

	//STEP %
	//Damn, this doesn't account for distance from the source, so probably need to multiply resulting light by 1 / (1+distFromSource + distFromCamera).
	float distFromCamera = (dot(pos3D - xCameraPos, pos3D - xCameraPos));
	
	float distFromSource = (dot(pos3D - xLightPos, pos3D - xLightPos));
	Output.LightingFactor = totalReflection / (1 + distFromSource * 1e-2);
	
	//STEP ^
	//Profit!
	return Output;    
}

PixelToFrame ColoredPS(MyVertexToPixel PSIn) 
{
	PixelToFrame Output = (PixelToFrame)0;		
    
	Output.Color = PSIn.Color;
	Output.Color.rgb *= saturate(PSIn.LightingFactor + 0.3);

	return Output;
}

technique Colored
{
	pass Pass0
	{   
		VertexShader = compile vs_2_0 ColoredVS();
		PixelShader  = compile ps_2_0 ColoredPS();
	}
}